#include "NGameEngine.h"

#include "NeroCore\NLogger.h"
#include "NeroCore\NMemoryManager.h"

#include "NeroEngine\NDevice.h"
#include "NeroEngine\NDebug.h"
#include "NeroEngine\NPlatform.h"

#include "NGame.h"

using namespace Game;
using namespace Engine;

extern std::string			GScene;
extern Game::NGame*			GGame;
extern bool					GIsRendering;
extern Engine::NPlatform*	GPlatform;

NGameEngine* NGameEngine::sInstance = NULL;

NGameEngine::NGameEngine(void)
	:NEngine()
{
}

NGameEngine::~NGameEngine(void)
{
}

void NGameEngine::Initialize()
{
	if(!sInstance)
	{
		sInstance = MY_NEW(Memory::HID_Engine, "GameEngine") NGameEngine();
		GGame->SetPlatform(GPlatform);
	}
}

void NGameEngine::Deinitialize()
{
	if(sInstance)
	{
		MY_DELETE(sInstance);
		sInstance = NULL;
	}
}

void NGameEngine::Run()
{
	GGame->Initialize(GScene);
	LOGD("Game is Running...");
	/*
		Game Loop
	*/
	while(!GGame->IsClosing())
	{
		HANDLE mutex = NDevice::sMutex;
		if(mutex)
		{
			DWORD dwWaitResult = WaitForSingleObject( mutex,		// handle to mutex
													  INFINITE);	// no time-out interval
			switch (dwWaitResult) 
			{
				case WAIT_OBJECT_0: 
					__try
					{
						GGame->Update(GetPlatform()->GetDeltaTime());
						//If not using threaded rendering
						if(!GIsRendering && !GGame->IsClosing())
						{
							GetPlatform()->Render();
						}
					}
					__finally
					{
						if (! ReleaseMutex(mutex)) // Release ownership of the mutex object
						{ 
							// Handle error.
						} 
					}
				break;
				case WAIT_ABANDONED: 
					break;
				default: 
					//no mutex create, no threading, run game normally
					GGame->Update(GetPlatform()->GetDeltaTime());
					break;
			}
		}
		else
		{
			GGame->Update(GetPlatform()->GetDeltaTime());
			GetPlatform()->Render();
		}
	}
	LOGD("Game is Closing...");
	GGame->Deinitialize();
}
